functor Irvc2vc (S : IRVC2VC_STRUCTS) : IRVC2VC =
struct
  open S
  
  structure I = Ir
  structure V = Vc
  
  local open I
  in structure Id = Id
     structure Intl = Intl
  end

  fun tr_b b = 
      case b
       of I.Plus => V.Plus
        | I.Minus => V.Minus
        | I.Times => V.Times
        | I.Divide => V.Divide
        | I.Modus => V.Modus
        | I.Band => V.Band
        | I.Bor => V.Bor
        | I.Equ => V.Equ
        | I.NEqu => V.NEqu
        | I.GT => V.GT
        | I.GE => V.GE
        | I.LT => V.LT
        | I.LE => V.LE
     
  fun tr_t t =
      case t
       of I.Int => V.Int
        | I.Bool => V.Bool
        | I.Void => V.Void
        | I.Struct s => V.Struct (Id.toString s)
        | I.Pointer ty => V.Pointer (tr_t ty)
        | I.Array (size, ty) => V.Array (size, tr_t ty)
    
  fun tr_e e =
      case e
       of I.Expvoid => V.Expvoid
        | I.IntNum i => V.IntNum i
        | I.True => V.True
        | I.False => V.False
        | I.Null => V.Null
        | I.Lval lval => V.Lval (tr_l lval)
        | I.BinopExp (e1, b, e2, pos) => V.BinopExp (tr_e e1, tr_b b, tr_e e2)
        | I.Not (e, pos) => V.Not (tr_e e)
        | I.Result => raise Fail "should not exist here\n"
        | I.Imply (e1, e2, pos) => V.Imply (tr_e e1, tr_e e2)
        | I.Forall (id, ty, e, pos) => V.Forall (Id.toString id, tr_t ty, tr_e e)
        | I.Exists (id, ty, e, pos) => V.Forall (Id.toString id, tr_t ty, tr_e e)
        | I.LList (exp, pos) => V.LList (tr_e exp)
        | I.Tree (exp, pos) => V.Tree (tr_e exp)
        | I.Pred (id, e, pos) => V.Pred (Id.toString id, tr_e e)
        | I.Let (e1, e2, e3, pos) => V.Let (tr_e e1, tr_e e2, tr_e e3)
        | _ => raise Fail "not implemented yet...\n"
                         
  and tr_l l =
      case l
       of I.Var (xxx, pos) => V.Var (Id.toString xxx)
        | I.Ptr (lval1, lval2, pos) => V.Ptr(tr_l lval1, tr_l lval2)
        | I.Sharp ty => V.Sharp(tr_t ty)
        | I.Inarray (lval, exp, size, pos) => V.Inarray(tr_l lval, tr_e exp)
        | I.Instruct (lval, id, pos) => V.Instruct(tr_l lval, Id.toString id)
        | I.Instruct2 (lval, id1, id2, pos) => V.Instruct2 (tr_l lval, Id.toString id1, Id.toString id2)
        | I.Upd (lval, e1, e2) => V.Upd(tr_l lval, tr_e e1, tr_e e2)
        | I.Sel (lval, e) => V.Sel(tr_l lval, tr_e e)
       
  fun newmap (s, vc) = (s, tr_e vc)
          
  fun top vclist =
      let val n_vcs = List.map newmap vclist
          fun local_opt (s, vc) = (s, V.topOpt vc)
          val opt_vcs : (Id.t * Vc.exp) list = List.map local_opt n_vcs
          fun ck (s, vc) = V.ckE vc
          val _ = List.map ck opt_vcs   
      in  (n_vcs, opt_vcs)
      end
end
